// TGFun.cpp: implementation of the TGSocket.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TGFun.h"
#include "winsock2.h"

#pragma comment(lib, "ws2_32.lib")

//////////////////////////////////////////////////////////////////////
BOOL TGCheckFileExist(char *pszFile)
{
	if( ::GetFileAttributes(pszFile) != 0xffffffff )
	{
		return TRUE;
	}
	return FALSE;
}

BOOL TGCreateDeepDir( char *pszDir )
{
	char szDir[260] = "";
	int nLength = (int)strlen(pszDir);

	for(int i=0;i<nLength;i++)
	{
		if( '\\' == pszDir[i] )
		{
			if( !TGCheckFileExist( szDir ) )
			{
				if( !::CreateDirectory(szDir,NULL) )
				{
					return FALSE;	
				}
			}
		}
		szDir[i] = pszDir[i];
	}

    return TRUE;
}

BOOL  TGDeleteDeepDir( char *pszDir )
{
	int nLength = 0;
	if( NULL == pszDir || ( nLength = (int)strlen(pszDir) ) < 4 )
	{
		return FALSE;
	}

	char szDir[260],szDirTemp[260];
	if( '\\' == pszDir[nLength-1] )
	{
		sprintf(szDir, "%s", pszDir);
	}
	else
	{
		sprintf(szDir, "%s\\", pszDir);
	}
	sprintf(szDirTemp,"%s*.*",szDir);
	
	WIN32_FIND_DATA FileData;
    HANDLE hFile = NULL;
	hFile = ::FindFirstFile(szDirTemp, &FileData); 
    if( INVALID_HANDLE_VALUE == hFile ) 
	{ 
		return FALSE; 
	} 

	BOOL bRet = FALSE;

	char szDirChild[260];
	while( TRUE )
	{
		sprintf(szDirChild, "%s%s", szDir,FileData.cFileName);
		if( FILE_ATTRIBUTE_DIRECTORY == FileData.dwFileAttributes )
		{
			if( strlen(FileData.cFileName)>0 && FileData.cFileName[0] != '.' )
			{
				if( !TGDeleteDeepDir(szDirChild) )
				{
					bRet = FALSE;
					break;
				}
				::RemoveDirectory(szDirChild);
			}
		}
		else
		{
			::DeleteFile(szDirChild);
		}

		if( !::FindNextFile(hFile, &FileData) )
		{
			if( ::GetLastError() == ERROR_NO_MORE_FILES ) 
			{ 
				bRet = TRUE;
				break;
			} 
			else
			{
				bRet = FALSE;
				break;
			}
		}
	}

	FindClose(hFile);

	return bRet;
}


BOOL TGCheckBufferSize(BYTE **ppBuffer,long &lSize,long lNewSize)
{
	if( lSize >= lNewSize )
	{
		return TRUE;
	}

	if( NULL == ppBuffer )
	{
		return FALSE;
	}

	if( NULL != *ppBuffer )
	{
		delete[]*ppBuffer;
		*ppBuffer = NULL;
	}

	*ppBuffer = new unsigned char[lNewSize+1];
	if( NULL == *ppBuffer )
	{
		return FALSE;
	}
	
	lSize = lNewSize;

	return TRUE;
}

BOOL TGAutoExpandBufferSize(BYTE **ppBuffer,long &lSize,long lNewSize)
{
	if( lSize >= lNewSize )
	{
		return TRUE;
	}

    BYTE *pNewBuffer = new BYTE[lNewSize+1];
	if( NULL == pNewBuffer )
	{
		return FALSE;
	}
	memset(pNewBuffer,0,lNewSize);

	if( NULL != *ppBuffer )
	{
		memcpy(pNewBuffer,*ppBuffer,lSize);
		delete[]*ppBuffer;
		*ppBuffer = NULL;
	}

	*ppBuffer = pNewBuffer;
	lSize     = lNewSize;

	return TRUE;
}


void TGMemCpyMMX(void* dst, void* src, unsigned int len)
{
	int nMainLen   = len/64*64;
	int nRemainLen = len%64;
	if( nMainLen > 0)
	{
		_asm
		{
			push esi
			push edi
			push edx
			mov esi, [src] ; source array
			mov edi, [dst] ; destination array
			mov ecx, [len] ; number of QWORDS (8 bytes) assumes len / CACHEBLOCK is an integer
			shr ecx, 6
			mov edx, 0
			nop;lea esi, [esi+ecx*8] ; end of source
			nop;lea edi, [edi+ecx*8] ; end of destination
			neg ecx ; use a negative offset as a combo pointer-and-loop-counter

copyloop:
			movq mm0, [esi+edx*8]
			movq mm1, [esi+edx*8+8]
			movq mm2, [esi+edx*8+16]
			movq mm3, [esi+edx*8+24]
			movq mm4, [esi+edx*8+32]
			movq mm5, [esi+edx*8+40]
			movq mm6, [esi+edx*8+48]
			movq mm7, [esi+edx*8+56]
			movq [edi+edx*8], mm0
			movq [edi+edx*8+8], mm1
			movq [edi+edx*8+16], mm2
			movq [edi+edx*8+24], mm3
			movq [edi+edx*8+32], mm4
			movq [edi+edx*8+40], mm5
			movq [edi+edx*8+48], mm6
			movq [edi+edx*8+56], mm7
			add edx, 8
			add ecx, 1
			jnz copyloop
			emms

			pop edx
			pop edi
			pop esi
		}
	}

	if( nRemainLen > 0 )
	{
		memcpy((unsigned char*)dst+nMainLen,(unsigned char*)src+nMainLen,nRemainLen);
	}
}

